package c2.group.business.teampvp;

import c2.advanced.business.common.fight.InternalFightHandler;
import cate.common.table.d.GDFight;
import cate.common.table.d.GDTeamPvp;
import cate.common.util.GameResult;
import cate.game.play.part.FightSide;
import cate.game.play.proce.play.PlayPO;
import cate.game.play.support.PlayBuildContext;
import cate.game.play.vo.ReplayUtils;
import cate.game.pvp.teampvp.TeamPvpReplayProfile;
import cate.game.pvp.teampvp.TeamPvpReport;
import cate.game.pvp.teampvp.TeamPvpTeamReplay;
import cp.solution.manage.api.open.OpenApi;
import cp.solution.manage.api.open.replay.ReplaySaveReq;
import cp.solution.manage.api.open.replay.ReplaySaveResp;
import easy.java.practice.errorcode.EcResult;
import lombok.extern.slf4j.Slf4j;

import java.time.ZoneId;
import java.util.ArrayList;
import java.util.function.Consumer;

@Slf4j
public class TeamPvpFightRunnableTask implements Runnable{
    InternalFightHandler handler;
    TeamPvpFightTask task;
    PlayBuildContext ctx;
    Consumer<TeamPvpReport> afterChallenge;
    OpenApi openApi;
    
    public TeamPvpFightRunnableTask(
            OpenApi openApi,
            InternalFightHandler handler,
            TeamPvpFightTask task,
            PlayBuildContext ctx,
            Consumer<TeamPvpReport> afterChallenge) {
        this.openApi = openApi;
        this.ctx = ctx;
        this.handler = handler;
        this.task = task;
        this.task.beginToFight();
        this.afterChallenge = afterChallenge;
    }

    @Override
    public void run() {
        try{
            log.info("有一场战斗开始拉, 挑战者uid={}", task.challengerUid);
            long start = System.currentTimeMillis();
            TeamPvpReport report = new TeamPvpReport();
            report.preScore = task.preScore;
            report.leaderUid = task.leaderUid;
            report.challengerUid = task.challengerUid;
            report.time = System.currentTimeMillis();
            report.list = new ArrayList<>();
            report.memberUids = task.memberUids;
            long delayTime = 0;
            for (int i = 0; i < 3; ++ i) {
                if (task.isAllFightsOver()) {
                    break;
                }
                FightSide fsa = FightSide.build(ctx, GDFight.Team.A, task.ateam.get(i).ps);
                FightSide fsb = FightSide.build(ctx, GDFight.Team.B, task.bteam.get(i).ps);
                GameResult<PlayPO> fightRes = handler.start(new TeamPvpFTC(), fsa, fsb);
                if (!fightRes.ok()) {
                    task.winner(GDFight.Team.B);
                    log.error("怎么就失败了呢？ r={}", fightRes.message);
                    continue;
                }
                PlayPO play = fightRes.data;
                play.startTime += delayTime;
                play.endTime += delayTime;
                delayTime += play.endTime - play.startTime;
                task.winner(play.winner);
                TeamPvpTeamReplay replay = new TeamPvpTeamReplay();
                replay.profile = TeamPvpReplayProfile.buildProfile(play);
                try{
                    ReplaySaveReq saveReq = ReplayUtils.toReplaySaveReq(play,
                            play.expiredDate.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
                    EcResult<ReplaySaveResp> saveRes = openApi.saveReplay(saveReq);
                    if (saveRes.ok()) {
                        replay.profile.replayUid = saveRes.data.getId();
                    }
                } catch (Exception e) {
                    log.error("段位赛保存录像出错", e);
                }
                report.list.add(replay);
            }
            report.win = task.awin();
            long teamsScoreDiff = task.bteamAverageScore() - task.ateamAverageScore();
            long scoreChange;
            if (report.win) {
                long winAdd = 45 + (long) (teamsScoreDiff * GDTeamPvp.WIN_SCALE);
                winAdd = Math.max(GDTeamPvp.WIN_SCORE_MIN, winAdd);
                scoreChange = Math.min(GDTeamPvp.WIN_SCORE_MAX, winAdd);
            } else {
                long loseAdd = 13 - (long) (teamsScoreDiff * GDTeamPvp.LOSE_SCALE);
                loseAdd = Math.min(GDTeamPvp.LOSE_SCORE_MAX, loseAdd);
                scoreChange = Math.max(GDTeamPvp.LOSE_SCORE_MIN, loseAdd);
            }
            report.score = scoreChange;
            afterChallenge.accept(report);
            log.info("组队竞技战斗耗时：{} ms", System.currentTimeMillis() - start);
        } catch (Exception e) {
            log.error("组队竞技战斗异常: ", e);
        } finally {
            task.endToFight();
        }
    }
}
